Symbol
剛開始學ruby的時候,看到一個變數前面有個 :
符號,那時想說這到底是什麼鬼東西,在寫的時候也很疑惑, 他跟變數有什麼差別,跟什麼時機要使用它呢?
可以把 Symbol 想像是一個「帶有名字的物件」。因為下面的一些特性,讓 Symbol 在 Ruby 中主要用作 hash 的鍵(key)或者是用來指稱方法的名稱。
symbol的重點整理
immutable: 被建立後就不能改變。
任何 symbol 都指稱到同一個記憶體位置,因此較省記憶體。
以 Symbol 當作鍵(key)的效能會比字串當作鍵的效能來得好。
# Symbol 都是以冒號(:)開頭
# Hash Rocket
new_hash = {
:one => 1,
:two => 2,
:three => 3
}
# 把冒號放在 symbol 的後面,並可省略 '=>'
# 不能寫 "one : 1",sybmol 後面要直接接':',不能先接空格
new_hash = {
one: 1,
two: 2,
three: 3
}
看起來跟指定變數很像,那Symbol 跟變數有什麼不同?
變數是一個指向某個物件的名字
greeting = "hello world"
上面這行語法,是指 greeting 這個名字指向 "Hello world" 這個字串物件,但如果沒有 "Hello world" 這個字串給它指定,這個名字本身是沒辦法單獨存在的。
而 Symbol 是一個「帶有名字的物件」,本身不需要指向任何東西也可以拿來用。而且你也沒辦法直接拿 Symbol 來當變數,像這樣會出現語法錯誤
:name = "kai" # 這得到 SyntaxError 的錯誤訊息
Symbol 跟字串有什麼不同?
Symbol 放在相同的記憶體位置
相同"樣子"的字串實際上都是在不同記憶體位置的不同物件,但是相同"樣子"的 Symbol 指稱到的是記憶體中的相同物件:
5.times do
puts "hello".object_id # 會得到 5 個不同的 id (表示是在 5 個不同記憶體位置的不同物件)
end
5.times do
puts :hello.object_id # 只會是同一個 id(直接從記憶體拿,不用重新產生)
end
Symbol 的效能比字串好
Symbol 的效能比字串要好一些,因為 Symbol 在做比較的時候,是直接比對這兩顆物件的 object id 是不是相同,而字串比較則是一個字母一個字母逐一比對。所以在效能上來說,字串在做比較的時間複雜度會隨著字母的數量(N)而增加,但 Symbol 的比較因為只比較是不是同一顆物件,所以它的複雜度是固定的。
因為 Symbol 不可變(immutable)的特性,以及它的查找、比較的速度比字串還快,它很適合用來當 Hash 的 Key。
字串的內容可以變,但 Symbol 不行
p :symbol # :symbol
p "symbol" # "symbol"
p :symbol[2] # m
p "symbol"[2] # m
:symbol[2] = "b" # return ERROR
"symbol"[2] = "b" # "sybbol"
字串跟 Symbol 是可以互相轉換的
# 字串轉成 Symbol
"name".to_sym
# Symbol 轉成字串
:name.to_s